package com.morth
{
	import flash.events.IOErrorEvent;
	import flash.events.TimerEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundMixer;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.Timer;
	
	import mx.collections.ArrayCollection;

	public class FadingSound
	{
		/** 
		 * Delay amount for the timer, in milliseconds.  Affects length of fades.
		 * */
		private var INTERVAL : int = 100;
		
		/**
		 * Minimum amount of time that a sound will play.
		 * */
		public static var MIN_PLAY_TIME : int = 1500;
		
 		public var isSoundPlaying:Boolean = false;
 		public var volume:Number = 1;
 		public var fadeInVolume:Number = 0;
 		// MAKE STATIC?
 		public var delay:Number = 8000;
 		
 		private var fadeOutChannel:SoundChannel;
 		private var currentSound:Sound = new Sound();;
 		private var currentChannel:SoundChannel = new SoundChannel();
 		private var playlist:ArrayCollection;
 		/**
 		 * The index of the currently playing track in playlist.
 		 * */
 		private var curTrack:Number = 0;
 		private var currentURL:String;
 		private var streamQueue:ArrayCollection=new ArrayCollection(new Array());
 		private var startTime:Number;
		private var isFading:Boolean = false;
		private var isFadingIn:Boolean = true;
		private var numTracksStoppedAfterFadeOut : Number = 0;
		internal var incrementIn : Number;
		internal var incrementOut : Number;
		internal var fadeInLength : Number;
		internal var fadeOutLength : Number;
		
 	// TRY TO USE FRAME EVENT, IF NOT, USE TIMER
 		private var timer:Timer;


		// volume change formula - INTERVAL /FADE_LENGTH
		public function play(tracks:ArrayCollection, fadeIn:Number = 2000, fadeOut:Number = 2000, duration:Number = 8000):void
		{
			//MIN_PLAY_TIME = minDuration;
			// save values for fade lengths
			incrementIn = INTERVAL / fadeIn;
			incrementOut = INTERVAL / fadeOut;
			fadeOutLength = fadeOut;
			fadeInLength = fadeIn;
			// MAX time for for a song to play
			delay = duration;
			
			timer = new Timer(INTERVAL);
			timer.addEventListener(TimerEvent.TIMER, onTimer);
			SoundMixer.stopAll();
			//clearTimers();
				//reset track count
				curTrack=0;
				numTracksStoppedAfterFadeOut=0;
				isFading = false;
				playlist = tracks;
				PlayNextSong();
				fadeOutChannel = currentChannel;
/* 			else
			{
				StopPlaylist();
			} */
		}
		
		///////////////////////
		// PlayNextSong
		///////////////////////
		private function PlayNextSong():void
		{	
			
			if (curTrack < playlist.length)
			{
				currentURL = playlist[curTrack];
				
				if (currentURL == null)
				{
					// since the URL is null, update the count and play the next song
					curTrack++;
					PlayNextSong();
				} 
				else
				{
					currentSound = new Sound();
					currentChannel=new SoundChannel();

					//add handler for ioerrors:
					currentSound.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true );
				
				//	addEventListener( Event.ENTER_FRAME, onEnterFrame, false, 0, true );
					timer.start();
					
					//load sound:
					var urlReq:URLRequest = new URLRequest(currentURL);
					currentSound.load(urlReq);
					
					currentChannel = currentSound.play(); //play sound:
					
					//currentChannel.addEventListener(Event.SOUND_COMPLETE, onPlayListSoundComplete);
					streamQueue.addItem(currentChannel);
					
					// set volume for fade in
					fadeInVolume = 0;
					changeVolume(fadeInVolume, currentChannel);

					isFadingIn = true;
					isSoundPlaying = true;
					
// now we should do some update to say which track is playing
					
					// update count
					curTrack++;
				}
			}
			else
			{
				//StopPlaylist();
			}
			
		}

		//public function onEnterFrame(delay:Number):void
		private function onTimer(event:TimerEvent):void
		{		
			// delay = how long until fade out starts
			// checkf or previews that are shorter than specified play length			
			//MIN_PLAY_TIME = default minimum play time
			if (delay > currentSound.length && currentSound.length > MIN_PLAY_TIME )
			{
				// the length is not correctly calculated until the song is fully loaded
				// which causes the player to think the song has already reached the delay time
				// and the player goes to the next song but also keeps playing the first one
				if ( currentSound.bytesLoaded < currentSound.bytesTotal )
				{
					// song is not fully loaded so ignore
					
				}
				else
				{
					// song is fully loaded and is shorter than the typical sample length
					delay = currentSound.length - fadeOutLength;
				}
			} 
			
			//////
			// FADE IN
			////
			
			if ( isFadingIn) 
				FadeIn();
				
			if ( currentChannel.position >= delay && !isFadingIn)
			{
				isFading = true;
			}
			// if
			if ( isFading) 
				FadeOut();
				trace(currentChannel.position);
		}
			  	// Changes the current volume to "value"
	  	private function changeVolume(value:Number, channel:SoundChannel):void
	  	{
			var fadeOut:SoundTransform = new SoundTransform;
			fadeOut.volume = value;
			channel.soundTransform = fadeOut;	  	
	  	}
	  	
	  	public function StopPlaylist():void
	  	{
	  		currentChannel.stop();
			isSoundPlaying = false;
			timer.stop();
			timer.removeEventListener(TimerEvent.TIMER, onTimer);
	  	}

		private function FadeOut():void
		{
			try
			{
				if ( volume == 1 && currentChannel)
				{
					fadeOutChannel = currentChannel;
					// originally there was a need to turn down the volume down .1
					// to prevent clipping during the fades.  
					// Keeping things simple and just using the interval
					volume -= incrementOut;	
					changeVolume(volume, fadeOutChannel);	
					PlayNextSong();
				}
					
				else if (0 < volume && volume< 1 )
				{
					volume -= incrementOut;
					changeVolume(volume, fadeOutChannel);
				}
				else if ( volume<= 0) 
				{
					fadeOutChannel.stop();
					numTracksStoppedAfterFadeOut++;
					if (streamQueue.length>0) 
						streamQueue.removeItemAt(0);
						
					volume = 1;
					isFading = false;
					
					// if we're just using this for 1 song, then we can stop the timer
					// TODO: stop timer on SoundComplete Event
					if (numTracksStoppedAfterFadeOut == playlist.length)
						StopPlaylist();
					}
			}
			catch (err:Error)
			{
				trace("error in FadeOut");
				//m.stopFrameEvents=true;
			}
		}
  	
  		private function FadeIn():void
		{
			try
			{
				if ( fadeInVolume == 0 && currentChannel)
				{
					fadeInVolume = incrementIn;
					// turn volume down to prevent clipping
					changeVolume(fadeInVolume, currentChannel);	
				//	PlayNextSong();
				}
					
				else if (0 <= fadeInVolume && fadeInVolume< 1 )
				{
					fadeInVolume += incrementIn;
					changeVolume(fadeInVolume, currentChannel);
				}
				else if ( fadeInVolume>= 1) 
				{
						
					fadeInVolume = 1;
					volume = 1;
					isFadingIn = false;
				
				// MAYBE?		StopPlaylist();
					}
			}
			catch (err:Error)
			{
				trace("error in FadeOut");
				//m.stopFrameEvents=true;
			}
		}
		
  		private function ioErrorHandler( evt:IOErrorEvent ):void
		{
			//Alert.show(evt.toString());
			PlayNextSong();
		}
	}
}